#include "pm.h"
#include <minix/callnr.h>
#include <signal.h>
#include <sys/svrctl.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <minix/com.h>
#include <minix/config.h>
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <minix/vm.h>
#include <string.h>
#include <machine/archtypes.h>
#include <lib.h>
#include <assert.h>
#include "mproc.h"
#include "param.h"
#include <stdio.h>

typedef struct Process {
	pid_t proc_nr;
} Process;

typedef struct Semaphore {
	int id;
	int value;
	Process processes[20];
	int numProc;
} Semaphore;

Semaphore sems[100];

int numOfSema = 0;
int recentSemaId = 0;

int do_seminit()
{
	printf("DO SEMINIT\n");
    int sem = m_in.m1_i1;
    int value = m_in.m1_i2;

	if(numOfSema == 100) {
		return EAGAIN;
	}
	
	if(sem < 0) {
		return EINVAL;
	}

	if(1000 < value || -1000 > value) {
		return EINVAL;
	}

	if(sem == 0) {
		sems[numOfSema].id = recentSemaId + 1;
		sems[numOfSema].value = value;
		sems[numOfSema].numProc = 0;
		numOfSema++;
		recentSemaId++;
	}
	else {
		int i;
		for(i = 0; i < 100; i++) {
			 /* if(sems[i]){ */
				if(sems[i].id == sem){
					return EEXIST;
				}
			/* } */
		}
		sems[numOfSema].id = sem;
		sems[numOfSema].value = value;
		sems[numOfSema].numProc = 0;
		numOfSema++;
		recentSemaId = sem;
	}

    return 0;
}

int do_semfree()
{
    int sem = m_in.m1_i1;
    printf("Sem: %d\n",sem);
    return 0;
}

int do_semdown()
{
    int sem = m_in.m1_i1;
    
	sems[sem].value--;
	if(sems[sem].value < 0) {
		int numOfProc = sems[sem].numProc;
		sems[sem].processes[numOfProc].proc_nr = mproc[who_p].mp_pid;
		sems[sem].numProc++;

		mp->mp_flags |= PAUSED;
		return(SUSPEND);
	}

    return 0;
}

int do_semup()
{
    int sem = m_in.m1_i1;
	sems[sem].value++;

	if(sems[sem].value < 1) {
		int rmp;
		for(rmp = 0; rmp < NR_PROCS; rmp++) {
			if(mproc[rmp].mp_pid == sems[sem].processes[0].proc_nr) {
				break;
			}
		}

		register struct mproc *lmp = &mproc[rmp];
		lmp->mp_flag |= REPLY;

		if(lmp->mp_flags & ONSWAP) {
			swap_inqueue(lmp);
		}
	}

    return 0;
}

int do_semvalue()
{
    int sem = m_in.m1_i1;
    
	/* if(sems[sem]) { */
		/* return sems[sem].value; */
	/* } */

	mp->mp_reply.reply_res2 = sems[sem].value;

    return 0;
}
